# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <sys/types.h>
# include <pthread.h>
# include <semaphore.h>
# include <string.h>
# include <unistd.h>

#define BUFFER_SIZE 5

//empty  同步信号量，表示剩余空间的数量
// full 同步信号量，表示产品的数量
// mutex 互斥信号量，实现对缓冲区的互斥访问
sem_t empty, full, mutex;

//缓冲区
int buffer[BUFFER_SIZE];

int in, out;

int flag;
//记录当前产品的数量
int cur=0;


//生产者
void *producer(void* param) {
    while (flag){
        sem_wait(&empty);
        sem_wait(&mutex);
        //生产产品
        buffer[in] = 1;
        in = (in+1)%BUFFER_SIZE;
        cur++;
        printf("Thread %d: Producer produce product,cur = %d \n", pthread_self(),cur);
        sem_post(&mutex);
        sem_post(&full);
    }
    pthread_exit(0);
}

//消费者
void *consumer(void* param) {

    while (flag){
        sem_wait(&full);
        sem_wait(&mutex);
        //消费产品
        buffer[out] = 0;
        out = (out+1)%BUFFER_SIZE;
        cur--;
        printf("Thread %d: Consumer consume product,cur = %d\n", pthread_self(),cur);
        sem_post(&mutex);
        sem_post(&empty);
    }
    pthread_exit(0);
}

int main() {
    //线程id
    pthread_t pro[10],cur[10];
    //对mutex进行初始化
    //第二个参数 不为０时此信号量在进程间共享，否则只能为当前进程的所有线程共享
    //第三个参数 给出了信号量的初始值。　　
    sem_init(&mutex, 0, 1);
    sem_init(&empty, 0, BUFFER_SIZE);
    sem_init(&full, 0, 0);

    in = out = 0;

    flag=1;

    for (int i = 0; i < 5; ++i) {
        //创建线程函数
        //第一个参数为指向线程标识符的指针。第二个参数用来设置线程属性。
        //第三个参数是线程运行函数的地址。 最后一个参数是运行函数的参数。
        pthread_create(&pro[i], NULL , producer, NULL);
        pthread_create(&cur[i], NULL , consumer, NULL);
    }
    //运行一秒
    sleep(1);

    flag = 0;
    for (int i = 0; i < 5; ++i) {
        //代码中如果没有pthread_join主线程会很快结束从而使整个进程结束，
        //从而使创建的线程没有机会开始执行就结束了。加入pthread_join后，主线程会一直等待直到等待的线程结束自己才结束，使创建的线程有机会执行
        //    第一个参数是等待退出线程的线程号
        //    第二个参数是返回值
        pthread_join(pro[i],NULL);
        pthread_join(cur[i],NULL);
    }
    return 0;
}
